#include <Globals.h>
#include <PageFaultHandler.h>
#include <MonitorDriver.h>
#include <SerialDriver.h>
#include <Asm.h>
#include <MemoryManagement.h>
#include <Kernel.h>
#include <Process.h>
#include <ProcessManager.h>

PageFaultHandler::PageFaultHandler()
 : InterruptServiceRoutine()
{
}


PageFaultHandler::~PageFaultHandler()
{
}

void PageFaultHandler::run(Registers *r)
{
  stopInterrupts();
  kerr.write("[FAULT\t] ", lightRed);
  kerr.write("(");
  if (processManager->getProcess()) kerr.writeHex(processManager->getProcess()->getPid());
  kerr.write(") ");
  kerr.write("Page fault at EIP=", green);
  kerr.writeHex(r->eip, green);
  kerr.write(", Faulty address=", green);
  
  u32int faultingAddress = getPageFaultAddress();
  
  kerr.writeHex(faultingAddress, green);

  bool p    = (r->err_code & 0x1) ? true : false;
  bool rw   = (r->err_code & 0x2) ? true : false;
  bool us   = (r->err_code & 0x4) ? true : false;
  bool rsvd = (r->err_code & 0x8) ? true : false;
  
  if (!p) // See intel manual -- p = 0 if page fault is due to a nonpresent page.
  {
    kerr.write(", Nonpresent page.\n", green);
  }
  if(rw)
  {
    kerr.write(", Write operation.\n", green);
  }
  if(us)
  {
    kerr.write(", In user mode.\n", green);
  }
  if(rsvd)
  {
    kerr.write(", Overwritten reserved bits.\n", green);
  }
  kernel.printBacktrace();
  
  if (processManager->getProcess())
  {
    DEBUG_MSG("Memory map:");
    processManager->getProcess()->memoryMap.dump();
  }
//   monitor << "EAX: " << hex << r.eax << 
//              "\tEBX: " << r.ebx << 
//              "\tECX: " << r.ecx << 
//              "\tEDX: " << r.edx <<
//              "\tESP: " << r.useresp << 
//              "\tCS: " << r.cs <<
//              "\tSS: " << r.ss <<
//              "\tESI: " << r.esi << 
//              "\tEDI: " << r.edi << 
//              "\tEBP: " << r.ebp << endl;
  
#ifdef AUTO_RESTART
  // Automatically restart the machine.
#endif
  for(;;);
}
